3W - 실리움 기본 - Routing, Masq, IP Frag

개요

이 노트도 이전 노트 내용에 이어 진행한다.
여기에서는 다음의 세 가지 내용을 다룬다.

Routing

실리움은 클러스터 내 파드 간 네트워킹을 전담하는 CNI로서 파드 IP로 통신이 가능하도록 트래픽을 적절히 라우팅해준다.
다른 노드 간 트래픽을 주고받기 위해 실리움은 두 가지 모드를 제공한다.[1]
image.png
캡슐 모드와 네이티브 라우팅 모드인데, 이름은 여기저기 다르지만 결국 뜻은 같다.

캡슐화(encapsulation) 모드

기본 설정으로, 파드의 트래픽을 말 그대로 터널을 뚫어서(캡슐화하여) 보낸다.
네트워크 인프라 단의 별도의 설정 없이 동작할 수 있는 모드이다.
이 모드에서는 UDP 기반의 캡슐 터널링 프로토콜이 사용된다.
VXLAN, Geneve 두 가지 프로토콜을 사용할 수 있다.

이 방식의 장점은 다음과 같다.

단점으로는 MTU 부하가 존재할 수 있다.
아무래도 패킷의 양이 늘어나고 자체 크기도 커질 수 있으며, 이는 처리량의 저하를 유발할 수 있다.
점보 프레임을 활성화해 이를 완화할 수는 있다.

이 부분은 다음에 별도로 실습을 진행하겠다.

네이티브 라우팅(native routing) 모드

routing-mode: native를 통해 활성화할 수 있는 모드로, 노드의 라우팅 테이블을 활용한다.

이전에 간단하게 노드의 환경에서는 각 파드로 향하는 인터페이스가 lxc로 보이는 것을 확인했다.
이 모드에서는 자신이 가진 파드에 대해서는 /32로 정확하게 해당 인터페이스로 트래픽을 보내고, 다른 노드의 IP 대역에 대해서는 해당 노드의 IP로 트래픽을 보내도록 라우팅 테이블을 설정한다.
그래서 내부로 들어가는 주소만 아니라면 모든 패킷을 라우팅 테이블에 의해 라우팅되며, 패킷은 로컬 프로세스가 보내는 패킷처럼 다뤄진다.
패킷 포워딩 커널 파라미터가 설정돼야 하는데 이 모드를 설정하면 실리움이 알아서 세팅도 해준다. 위험한 놈

패킷을 캡슐화하지 않고 그대로 보내니 캡슐화하는데 들어가는 자원 소모는 없고 상대적으로 빠른 속도가 보장된다.
다른 CNI 프로바이더들은 대체로 캡슐화 방식을 사용하는데 반해 실리움이 가진 강점 중 하나라 할 수 있겠다.

참고로 라우팅 테이블을 사용한다는 것은 노드 별로 다른 PodCIDR이 있기에 가능한 것이다.
그런 만큼 몇 가지 제약이 있다.

실습

초기 클러스터 구축 시 네이티브 라우팅으로 세팅했기 때문에 상태를 확인하고 트래픽을 뜯어보는 정도만 하고자 한다.
라우팅 테이블은 단순하게 보기만 하면 된다.

vagrant ssh k8s-ctr -c 'ip -c route'
vagrant ssh k8s-w1 -c 'ip -c route'

image.png
보다시피 파드가 생긴 만큼 이에 해당하는 인터페이스로 빠지라는 경로 규칙이 설정된 것을 볼 수 있다.
또한 각 테이블에서는 서로의 노드 IP 대역에 대해 각 노드로 트래픽을 보내라는 규칙도 작성되어 있다.
이를 통해 클러스터 IP 대역의 트래픽이 발생했을 때 성공적으로 각 노드로 가게 될 것이란 것을 보장할 수 있다.

그렇다면 실제로 트래픽을 보내면서 패킷도 간단하게 확인해보자.

export WEBPODIP1=$(kubectl get -l app=webpod pods --field-selector spec.nodeName=k8s-ctr -o jsonpath='{.items[0].status.podIP}')
export WEBPODIP2=$(kubectl get -l app=webpod pods --field-selector spec.nodeName=k8s-w1  -o jsonpath='{.items[0].status.podIP}')
kubectl exec -it curl-pod -- ping $WEBPODIP2

hubble observe -f --pod curl-pod --ip-translation=false

# 여기는 vm 들어가서 확인
tcpdump -i any icmp -w /tmp/icmp.pcap
termshark -r /tmp/icmp.pcap

허블로 볼 때 신원이 아니라 주소로 확인할 때는 위와 같이 옵션을 주면 된다.
image.png
아무튼 IP에 대한 일체의 변경 없이 트래픽이 전달되고 있는 것을 볼 수 있다.

any로 걸어서 트래픽을 뜯어보면 다음과 같이 4개의 덤프가 하나의 ping 요청 응답을 이룬다.
image.png

각각의 인터페이스 번호를 확인해보면 이것을 조금 더 명확하게 볼 수 있다.
image.png
내 경우엔 21번 인터페이스와 3번 인터페이스가 사용됐는데, 파드의 인터페이스가 21번이고 실제로 트래픽이 나갈 때 사용되는 eth1이 3번 인터페이스였다.
image.png

Masquerading

마스커레이딩이란

마스커레이딩은 간단하게 말하자면 NAT이다.
조금 더 구체적으로는 LAN에서 외부로 나가는 트래픽을 위해 공인 IP로 소스 IP를 바꾸는 작업을 마스커레이딩이라 표현한다.[2]
처음에는 왜 굳이 이렇게 부르는가 했는데, 하나의 이그레스 게이트웨이에서 여러 노드의 트래픽이 나갈 때 다시 각 노드로 응답이 잘 돌아가게끔 적절하게 트래픽의 출처를 기록하고 관리해야 하기 때문에 특별하게 부른다.
이런 상황에서 쓰는 게 가장 흔할 것이다.
image.png
하나의 LAN에서 외부로 트래픽을 라우터를 거쳐서 보내는 상황이다.
이때 라우터는 나간 트래픽이 돌아올 수 있도록 출발 IP를 자신으로 바꾸고, 응답이 돌아왔을 때는 목적지 IP를 LAN 속 호스트로 바꿀 것이다.
이러한 작업 전반을 마스커레이딩이라 부르고, 이렇게 트래픽이 나가는 게이트웨이를 Masq 게이트라고도 한다.
리눅스를 통해 마스커레이딩을 할 때는 기본적으로 넷필터를 통해 수행할 수 있다.
그래서 iptables에서도 보면 액션 중에 MASQ 동작이 따로 존재하는데, 대신 포워딩과 같은 커널 모듈로딩이 필요하다.

실리움의 마스커레이딩

실리움에서는 이러한 마스커레이딩 동작에 대한 커스텀 기능을 지원한다.
기본적인 실리움의 동작은 클러스터를 떠난다 싶은 모든 트래픽에 대해 마스커레이딩을 하는 것이다.
이건 어딜 가든 사실 매우 당연한 동작이긴 하나, 만약 사내망과 같은 상황에서 라우팅 경로 설정이 이미 잘 돼 있고 또한 파드의 IP를 보존하는 것이 보안 요건 상 요구되는 것이라면 이런 것들을 커스텀할 수 있는 것이다.

마스커레이딩도 두 가지 모드가 있는데 하나는 위에서 말한 넷필터, 즉 iptables 기반으로 하는 것이다.
이 방식이 가장 기본적이라 할 수 있는데 문서에서는 레거시라 표현하며, 자신들이 만든 ebpf 모드도 같이 소개한다.

기본 실습

이번에도 기본 설정으로 bpf 기반 마스커레이딩을 활성화해둔 상태이니 어떤지 체크만 하고 간다.

kubectl -n kube-system exec ds/cilium -- cilium-dbg status | grep Masquerading

image.png
현재 ebpf 기반의 마스커레이딩이 eth0, eth1에 대해 활성화돼있으며, 파드 IP 대역으로 나가는 트래픽에 대해서는 마스커레이딩을 진행하지 않도록 설정돼있다.
(멀티 풀 관련 세팅하다가 10.244쪽 대역으로 설정이 돼버렸다.)
해당 대역은 ipv4-native-routing-cidr 값으로 설정된 것으로 네이티브 라우팅을 위한 설정값을 그대로 읽어서 마스커레이딩 제외 구간으로 활용하는 것이다.[3]

같은 대역에서는 마스커레이딩이 되지 않는다는 걸 이전 실습에서 충분히 확인할 수 있었다.
image.png
그렇다면 위에서 설정한 라우터로의 통신은 어떻게 될까?

kubectl exec -it curl-pod -- ping 192.168.10.200 
kubectl exec -it curl-pod -- curl -s 10.10.1.200 

# k8s-ctr 실행
hubble observe -f --pod curl-pod --ip-translation=false 
# router에서  실행
tcpdump -i eth1 port 80 -nn

라우터로 사용한 vm은 노드와 같은 대역으로 192 대역을 사용하고, 더미 인터페이스를 두어 10.10대역에 대해서도 ip를 할당받았다.
그리고 각 노드에서는 해당 대역에 대해 라우터 vm으로 통하게 만들어두었다.
이 상태에서 트래픽을 보내는 파드가 있는 노드에서도, 실제 트래픽을 받은 라우터에서도 트래픽을 측정해본다.
image.png
트래픽을 보내는 측에서는 나가기 전까지는 파드의 ip가 그대로 유지된다.
그러나 실제로 트래픽이 나가는 순간에는 bpf 마스커레이딩이 적용된다.
그래서 라우터가 트래픽을 받을 때는 192.169.10.100, 즉 노드의 IP가 보이게 된다.
현재 설정 상 파드 IP 대역에 대해 라우터 vm에 경로 설정을 하지 않았으므로 마스커레이딩이 없다면 트래픽은 제대로 돌아오지 못하게 될 것이다.

ip-masq-agent

여기에 추가적인 내용으로, ebpf 모드 마스커레이딩은 ip-masq-agent의 기능도 지원한다.
쿠버네티스에서는 세부적인 범위에 대해서, 특정 IP만 구체적으로 마스커레이딩을 설정하고 싶다던가 하는 수요를 위해 ip-masq-agent라는 별도의 에이전트를 제공하고 있다.[4]
여기에서는 댜음의 설정을 통해 구체적인 마스커레이딩 커스텀이 가능하다.

실리움은 이걸 또 ebpf 기반으로 만들어서 제공하고 있는 것이다.
다음의 상황에서 유용하게 사용할 수 있을 것으로 보인다.

실습

간단하게 활성화하고, 대역을 지정해서 넣어주면 된다.

helm upgrade cilium cilium/cilium --namespace kube-system --reuse-values \
--set ipMasqAgent.enabled=true --set ipMasqAgent.config.nonMasqueradeCIDRs='{10.10.1.0/24,10.10.2.0/24}'

image.png
해당 세팅은 컨피그맵으로 들어가게 되며, 이 값에 대한 변경은 자동으로 에이전트에 반영될 것이다.

이 상태에서 위에서 날린 패킷을 그대로 똑같이 날려보면..
image.png
트래픽은 분명히 날아온다.
그러나 라우터 측의 캐핏을 보면 알 수 있듯이 정말 파드의 ip가 마스커레이딩되지 않고 그대로 날아오며 이에 따라 응답이 돌아갈 곳이 없어 제대로 된 통신이 진행되지는 않는다.
아예 프로토콜을 한정시키지 않고 패킷을 따면 상황이 더 확실해진다.
image.png
라우터는 패킷을 받긴 했는데 출발지가 이상하게 적혀있으니 돌려줄 것으로 몰라서 계속 arp로 여기가 어디냐 소리없는 아우성을 외친다..

이걸 처리하고 싶다면 트래픽을 보내는 측(k8s-ctr)에서 해당 ip가 내 ip다 이야기할 수 있는 상태가 돼야 한다.

ip a add 10.244.0.99 dev eth1

image.png
(10.249는 오타..)
이러면 arp 요청에 대해 해당 인스턴스가 자신의 MAC 주소를 밝히게 되고, 결과적으로 응답이 정상적으로 돌아갈 수 있게 된다.
image.png

IP fragment handling

기본 기능으로서 마지막으로 볼 것은 IP 조각 처리이다.[5]
이건 기본 기능이라기보단.. 그냥 패킷을 조금 더 효율적으로 보내는 기술에 대한 개념이다.
이것 역시 현재 베타인 기능이다.

TCP의 경우 모든 데이터를 순서대로 확실하게 전달하기 위해 데이터를 쪼개(세그멘테이션) 번호를 붙여 전달하는 반면 UDP는 그냥 어련히 받겠거니 패킷을 던져버린다.
이때 UDP로 큰 데이터그램을 던지는 경우, L3인 IP 레벨에서 조각화(fragmentation)이 발생할 수 있으며, 이때 받는 측은 예상치 못한, 정말 신뢰할 수 없는 조각들을 받게 될 수도 있다.
큰 크기를 가진 트래픽을 전송할 때 실리움은 ebpf 데이터 경로를 구성해 조각 추적을 진행한다.
조각이 발생할 때 이를 bpf map으로 관리하면서 조각화된 데이터그램 단위가 제대로 전송될 수 있도록 도와준다는 것이다.

이 부분도 실습을 통해 확인을 해보면 좋을 것 같은데 어떻게 큰 규모의 UDP 데이터그램을 만들어낼 수 있을지 아이디어가 부족해 이 부분은 당장은 문서 정리로만 남겨두고자 한다.
image.png
이 기능은 기본 활성화돼있는 상태이다.
실제 조각화가 발생하여 bpf에서 이를 처리하게 되면 다음의 메트릭이 노출될 것이다.

cilium_bpf_map_pressure{map_name="cilium_ipv4_frag_datagrams"}

결론

보면 볼수록 실리움은 ebpf를 쓰는 CNI라는 한 마디로 표현하기에는 매우 다양한 기능을 가지고 있고, 또 그러한 방향으로 나아가고 있는 것 같다.
그 다양한 기능이 문서에 잘 정리돼있는가 하면.. 그 부분은 좀 의구심이 들긴 하는데, 아무튼 각 기능들을 이해하려고 들다보니 트래픽을 어떻게 최적화를 할 수 있는가에 대한 식견이 조금 넓어지는 느낌이다.

이전 글, 다음 글

다른 글 보기

이름 index noteType created
1W - 실리움 기본 소개 1 published 2025-07-19
1W - 클러스터 세팅 및 cni 마이그레이션 2 published 2025-07-19
1W - 기본 실리움 탐색 및 통신 확인 3 published 2025-07-19
2W - 허블 기반 모니터링 4 published 2025-07-26
2W - 프로메테우스와 그라파나를 활용한 모니터링 5 published 2025-07-26
3W - 실리움 기본 - IPAM 6 published 2025-08-02
3W - 실리움 기본 - Routing, Masq, IP Frag 7 published 2025-08-02
4W - 실리움 라우팅 모드 실습 - native, vxlan, geneve 8 published 2025-08-09
4W - 실리움 로드밸런서 기능 - 서비스 IP, L2 9 published 2025-08-09

하위 문서

이름 is-folder index noteType created
1W - 실리움 기본 소개 false 1 published 2025-07-19
1W - 클러스터 세팅 및 cni 마이그레이션 false 2 published 2025-07-19
1W - 기본 실리움 탐색 및 통신 확인 false 3 published 2025-07-19
2W - 허블 기반 모니터링 false 4 published 2025-07-26
2W - 프로메테우스와 그라파나를 활용한 모니터링 false 5 published 2025-07-26
3W - 실리움 기본 - IPAM false 6 published 2025-08-02
3W - 실리움 기본 - Routing, Masq, IP Frag false 7 published 2025-08-02
4W - 실리움 라우팅 모드 실습 - native, vxlan, geneve false 8 published 2025-08-09
4W - 실리움 로드밸런서 기능 - 서비스 IP, L2 false 9 published 2025-08-09

관련 문서

지식 문서, EXPLAIN

이름5is-folder생성 일자
설치 요구사항false2025-07-06 10:34
ebpf 동작 가이드false2025-07-06 10:49
Hubblefalse2025-07-06 10:38
0주차 검증false2025-07-06 12:46
Ciliumfalse2025-06-15 23:42

기타 문서

Z0-연관 knowledge, Z1-트러블슈팅 Z2-디자인,설계, Z3-임시, Z5-프로젝트,아카이브, Z8,9-미분류,미완
이름16코드타입생성 일자
4W - 실리움 로드밸런서 기능 - 서비스 IP, L2Z8published2025-08-09 21:56
4W - 실리움 라우팅 모드 실습 - native, vxlan, geneveZ8published2025-08-09 20:22
1W - 실리움 기본 소개Z8published2025-07-19 22:44
실리움 1주차Z8topic2025-07-13 19:50
실리움 개괄Z8topic2025-07-19 11:00
기본 실리움 탐색 및 통신 확인Z8topic2025-07-19 23:05
클러스터 세팅 및 cni 마이그레이션Z8topic2025-07-19 10:13
실리움 2주차Z8topic2025-07-20 19:05
노드로컬 dnsZ8topic2025-08-02 12:57
실리움 3주차Z8topic2025-07-27 19:44
1W - 클러스터 세팅 및 cni 마이그레이션Z8published2025-07-19 23:38
3W - 실리움 기본 - IPAMZ8published2025-08-02 19:48
1W - 기본 실리움 탐색 및 통신 확인Z8published2025-07-19 23:45
Cilium 공식 문서 핸즈온 스터디Z8published2025-07-05 20:47
2W - 프로메테우스와 그라파나를 활용한 모니터링Z8published2025-07-26 21:15
2W - 허블 기반 모니터링Z8published2025-07-26 21:08

참고


  1. https://docs.cilium.io/en/stable/network/concepts/routing/ ↩︎

  2. https://www.ibiblio.org/pub/linux/docs/howto/other-formats/html_single/IP-Masquerade-HOWTO.html#IPMASQ-INTRO1.1 ↩︎

  3. https://docs.cilium.io/en/stable/network/concepts/masquerading/#ebpf-based ↩︎

  4. https://kubernetes.io/docs/tasks/administer-cluster/ip-masq-agent/ ↩︎

  5. https://docs.cilium.io/en/stable/network/concepts/fragmentation/ ↩︎